package com.soccertgc.core
{
	import flash.events.Event;
	
	public class Stats extends DispatcherDataObject
	{
		
		// -------------------------------------------------------------------------------
		// CONSTANTS
		// -------------------------------------------------------------------------------

		// JSON data properties names
		public static const 	JSON_PROPERTY_STAMINA:String		= "stamina";
		public static const 	JSON_PROPERTY_DRIBLING:String		= "dribbling";
		public static const 	JSON_PROPERTY_PASSING:String		= "passing";
		public static const 	JSON_PROPERTY_SCORING:String		= "scoring";
		public static const 	JSON_PROPERTY_DEFENCE:String		= "defense";
		public static const 	JSON_PROPERTY_GOALKEEPING:String	= "goalkeeping";
		
		// Default values
		private static const 	DEFAULT_STAMINA:int					= 6;
		private static const 	DEFAULT_DRIBLING:int				= 6;
		private static const 	DEFAULT_PASSING:int					= 6;
		private static const 	DEFAULT_SCORING:int					= 6;
		private static const 	DEFAULT_DEFENCE:int					= 6;
		private static const 	DEFAULT_GOALKEEPING:int				= 0;
		
		// Events
		public static const     EVENT_STATS_CHANGED:String			= "stats_changed";
		
		// -------------------------------------------------------------------------------
		// FIELDS
		// -------------------------------------------------------------------------------
		
		protected var _stamina:int;
		protected var _dribiling:int;
		protected var _passing:int;
		protected var _scoring:int;
		protected var _defence:int;
		protected var _goalkeeping:int;
		
		// -------------------------------------------------------------------------------
		// CONSTRUCTOR
		// -------------------------------------------------------------------------------
		
		public function Stats()
		{
			// Call ancestor
			super();
			// Clears data
			clear();
		}
		
		// -------------------------------------------------------------------------------
		// PROPERTIES
		// -------------------------------------------------------------------------------
		
		[Bindable(event="stats_changed")]
		public function get stamina():int
		{
			return _stamina;
		}
		
		public function set stamina(value:int):void
		{
			_stamina = value;
		}
		
		[Bindable(event="stats_changed")]
		public function get dribiling():int
		{
			return _dribiling;
		}
		
		public function set dribiling(value:int):void
		{
			_dribiling = value;
		}
		
		[Bindable(event="stats_changed")]
		public function get passing():int
		{
			return _passing;
		}
		
		public function set passing(value:int):void
		{
			_passing = value;
		}
		
		[Bindable(event="stats_changed")]
		public function get scoring():int
		{
			return _scoring;
		}
		
		public function set scoring(value:int):void
		{
			_scoring = value;
		}
		
		[Bindable(event="stats_changed")]
		public function get defence():int
		{
			return _defence;
		}
		
		public function set defence(value:int):void
		{
			_defence = value;
		}

		[Bindable(event="stats_changed")]
		public function get goalkeeping():int
		{
			return _goalkeeping;
		}

		public function set goalkeeping(value:int):void
		{
			_goalkeeping = value;
		}
		
		// -------------------------------------------------------------------------------
		// PRIVATE METHODS
		// -------------------------------------------------------------------------------
		
		// DataObject implementation
		
		override protected function validate(data:Object):void
		{
			if (!data.hasOwnProperty(JSON_PROPERTY_STAMINA)) 		throwLoadMissingPropError("stamina");
			if (!data.hasOwnProperty(JSON_PROPERTY_DRIBLING)) 		throwLoadMissingPropError("dribling");
			if (!data.hasOwnProperty(JSON_PROPERTY_PASSING)) 		throwLoadMissingPropError("passing");
			if (!data.hasOwnProperty(JSON_PROPERTY_SCORING)) 		throwLoadMissingPropError("scoring");
			if (!data.hasOwnProperty(JSON_PROPERTY_DEFENCE)) 		throwLoadMissingPropError("defence");
			if (!data.hasOwnProperty(JSON_PROPERTY_GOALKEEPING))	throwLoadMissingPropError("goalkeeping");
		}
		
		override protected function fill(data:Object):void
		{
			_stamina 		= int(data[JSON_PROPERTY_STAMINA]);
			_dribiling 		= int(data[JSON_PROPERTY_DRIBLING]);
			_passing 		= int(data[JSON_PROPERTY_PASSING]);
			_scoring 		= int(data[JSON_PROPERTY_SCORING]);
			_defence 		= int(data[JSON_PROPERTY_DEFENCE]);
			_goalkeeping	= int(data[JSON_PROPERTY_GOALKEEPING]);
			// Dispatch event EVENT_STATS_CHANGED
			dispatchStatsChanged();
		}
		
		// Events dispatcher
		
		protected function dispatchStatsChanged():void
		{
			dispatchEvent(new Event(EVENT_STATS_CHANGED));
		}
		
		// -------------------------------------------------------------------------------
		// PUBLIC METHODS
		// -------------------------------------------------------------------------------
		
		/**
		 * Updates the current status, merging the values of the given object 
		 * @param stats
		 * @return New Stats object containing the stats obtained subtracting
		 * given stats value from the instance Stats values
		 */		
		public function update(stats:Stats):void
		{
			// Merges the current stats with the provided one
			var merge:Stats = merge(stats);
			// Copies data from the merged object
			copy(merge);
		}
		
		/**
		 * Creates a new Stats object as the result of the merge of the values of each Stat value
		 * @param stats
		 * @return New Stats object containing the stats obtained merging the two objects
		 */		
		public function merge(stats:Stats):Stats
		{
			// Stats merge
			var stam:int 	= _stamina		+ stats.stamina;
			var drib:int 	= _dribiling	+ stats.dribiling;
			var pass:int 	= _passing		+ stats.passing;
			var scor:int 	= _scoring		+ stats.scoring;
			var def:int 	= _defence		+ stats.defence;
			var goal:int = _goalkeeping	+ stats.goalkeeping;
			// Stats object
			var delta:Stats = new Stats();
			delta.stamina 		= stam;
			delta.dribiling 	= drib;
			delta.passing 		= pass;
			delta.scoring 		= scor;
			delta.defence 		= def;
			delta.goalkeeping	= goal;
			// Returns the Stats
			return delta;
		}
		
		public function equals(stats:Stats):Boolean
		{
			return	_stamina		== stats.stamina		&&
					_dribiling		== stats.dribiling		&&
					_passing		== stats.passing		&&
					_scoring		== stats.scoring		&&
					_defence		== stats.defence		&&
					_goalkeeping	== stats.goalkeeping;
		}
		
		public function copy(stats:Stats):void
		{
			// Check differences
			if (!equals(stats))
			{
				// Updates the stats
				_stamina		= stats.stamina;
				_dribiling		= stats.dribiling;
				_passing		= stats.passing;
				_scoring		= stats.scoring;
				_defence		= stats.defence;
				_goalkeeping	= stats.goalkeeping;
				// Dispatch event EVENT_STATS_CHANGED
				dispatchStatsChanged();
			}
		}
		
		public function clone():Stats
		{
			var stats:Stats = new Stats();
			stats.copy(this);
			return stats;
		}

		override public function clear():void
		{
			// Restore defailt values
			_stamina 		= DEFAULT_STAMINA;
			_dribiling		= DEFAULT_DRIBLING;
			_passing		= DEFAULT_PASSING;
			_scoring		= DEFAULT_SCORING;
			_defence		= DEFAULT_DEFENCE;
			_goalkeeping	= DEFAULT_GOALKEEPING;
			// Dispatch event EVENT_STATS_CHANGED
			dispatchStatsChanged();
		}
		
		// -------------------------------------------------------------------------------
		// STATIC METHODS
		// -------------------------------------------------------------------------------
		
		/**
		 * Check if the given pro name string is a valid stat contained by a Stat object 
		 * @param statName Stat property name to check
		 * @return True is the stat name is a valid stat property
		 */
		public static function isBaseStatName(statName:String):Boolean
		{
			return	statName == JSON_PROPERTY_DEFENCE	||
					statName == JSON_PROPERTY_STAMINA	||
					statName == JSON_PROPERTY_DRIBLING	||
					statName == JSON_PROPERTY_PASSING	||
					statName == JSON_PROPERTY_SCORING	||
					statName == JSON_PROPERTY_DEFENCE	||
					statName == JSON_PROPERTY_GOALKEEPING;
		}
		
	}
}